#!/usr/local/bin/php
<?php
ini_set('default_socket_timeout', -1);
define("APP_PATH", __DIR__);
echo "开始启动：".date("y-m-d H:i:s")."-----------------\r\n";
class SubCommissionModule {

    protected  $pdb = null;
    protected  $redis = null;

    protected function _init() {
        $this->pdb = new \PDO("mysql:host=129.204.245.7;port=3306;dbname=miaomeimei", "miaomeimei", "4GShwE84Bww7spat" ,[\PDO::ATTR_ERRMODE =>\PDO::ERRMODE_EXCEPTION, \PDO::MYSQL_ATTR_INIT_COMMAND =>"SET NAMES utf8"]);
//        $this->pdb = new \PDO("mysql:host=129.204.245.7;port=3306;dbname=miaommei", "zengYe", "jksdklxsklda*@!ds123" ,[\PDO::ATTR_ERRMODE =>\PDO::ERRMODE_EXCEPTION, \PDO::MYSQL_ATTR_INIT_COMMAND =>"SET NAMES utf8"]);
        $this->pdb->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION );
//        $this->redis = new \Redis();
//        $this->redis->pconnect(REDIS_HOST, REDIS_PORT , 2.4, 'corex');
//        $this->redis->auth(REDIS_AUTH);
//        $this->redis->select(REDIS_DB_INDEX);
    }

    /*
     * 自动计算
     * type  1-分享 2-团队
     */
    public function autoCalculate($type,$oid){
        $this->_init();
        try{
            $mtype = '2,4,6,7';
            if($type == 1){
                $where = " where m.oid={$oid} and m.type in ($mtype) and m.status=2 and m.is_delete=0";
            }else{
                $where = " where m.oid={$oid} and m.type=3 and m.status=2 and m.is_delete=0";
            }
            $sm = $this->pdb->query("Select m.uid,m.type,m.oid,m.reward,m.status,m.money,m.proportion,o.uid as ouid from m3_miao_log m LEFT JOIN m3_order o ON (o.id=m.oid) {$where}", \PDO::FETCH_ASSOC);
            $fRows = $sm->fetchAll();
            if(empty($fRows)){
                echo "订单：{$oid} 的miaolog为空无法结算,data:".date('Y-m-d H:i:s').PHP_EOL;
                return false;
            }
            $uid = 0;$money = 0;$order = [];
            foreach ($fRows as $key => $val) {
                $uid = $val['ouid'];
                //$money = $val['money'];
                //$order[$val['uid']] = $val;
                break;
            }
            if($type == 2) $err = $this->teamSettlement($uid,$fRows,$oid);
            else $err = $this->shareSettlement($uid,$fRows,$mtype);

            if($err != true) echo $err.PHP_EOL;
            else echo "V1.0 Complete!".PHP_EOL;

            return true;
        }catch(\PDOException $e){
            var_dump($e->getMessage());
            return false;
        }catch(\Exception $e){
            var_dump($e->getMessage());
            return false;
        }
    }

    /*
     * 团队结算
     */
    public function teamSettlement($uid,$order,$oid){
        try{
            if(empty($uid)) throw new \Exception('没有可分配用户！');
            if(empty($order)||!is_array($order)) throw new \Exception('没有可分配订单！');
            #用户按等级排序
            $userIds = $userM = $userInvite = [];
            $puserIds = $this->loopTop($uid);
            if(!empty($puserIds)){
                $arr = explode(',',$puserIds['level']);
                $userIds = array_reverse($arr);
            }
            /*$sm = $this->pdb->query("Select id as uid,`level`,binding_time from m3_user  WHERE id in ({$puserIds['level']},{$uid})", \PDO::FETCH_ASSOC);
            $pUsers = $sm->fetchAll();*/
            $row = [];
            $reward = 0;
            $money = 0;
            foreach($order as $k=>$v){
                $reward = $v['reward'];
                $money = $v['money'];
                $row[$v['uid']] = $v;
            }
            foreach($userIds as $key=>$val){
                if(isset($row[$val])&&$val!=$uid){
                    $userInvite[$key] = !empty($userInvite[$key]) ? array_merge($userInvite[$key], $row[$val]) : $row[$val];
                }elseif($uid != $val){
                    $userInvite[$key] = ['uid'=>$val,'money'=>$money,'reward'=>$reward,'oid'=>$oid];
                }
                /* foreach($pUsers as $keys=>$value){
                     if($value['uid'] == $uid) $userM = empty($userM)? $value : array_merge($userM, $value);
                     if($value['uid'] == $val){
                         $userInvite[$key] = !empty($userInvite[$key]) ? array_merge($userInvite[$key], $value) : $value;
                     }
                 }*/
            }

            #按等级进行分佣 同等级按管理津贴算，非同等级按团队佣金算
            $wallet = [];$i = 1;$time = time();
            $sql_update = $this->pdb->prepare("Update m3_user_wallet set miao=miao+?,miaos=miaos+?,consume=consume+?,teams=teams+?,wait_miao=IF(wait_miao-?<0,0,wait_miao-?) where uid=?");
            $sql_update2 = $this->pdb->prepare("Update m3_miao_log set `status`=?,`end_time`={$time} where oid=? and `type`=3");
            $sql_update4 = $this->pdb->prepare("insert into m3_user_info (uid,consume,team_consume,team_order_num)  values(?,?,?,?) on  DUPLICATE key update consume=consume+values(consume),team_consume=team_consume+values(team_consume),team_order_num=team_order_num+values(team_order_num)");
            $this->pdb->beginTransaction();
            #更新个人消费记录
            $wallet[0] = ['uid'=>$uid,'reward'=>$money,'status'=>1,'type'=>3,'extend'=>'order','extend_id'=>$oid,'add_time'=>$time,'describe'=>'个人累计消费'];
            if(!empty($puserIds)){
                $sql_update4->execute([ $uid, $money, 0, 1 ]);//更新用户绑定后消费数据
            }
            $sql_update->execute([ 0, 0, $money, 0, 0, 0, $uid ]);
            foreach($order as $k=>$v){
                $wallet[$i] = ['uid'=>$v['uid'],'reward'=>$v['money'],'status'=>1,'type'=>3,'extend'=>'order','extend_id'=>$oid,'add_time'=>$time,'describe'=>'团队累计消费'];
                if($v['reward']>0){
                    $i=$i+1;
                    $wallet[$i] = ['uid'=>$v['uid'],'reward'=>$v['reward'],'status'=>1,'type'=>2,'extend'=>'order','extend_id'=>$oid,'add_time'=>$time,'describe'=>'购买商品团队结算(喵呗)&扣除待结算记录'];
                }
                $sql_update->execute([ $v['reward'], $v['reward'], 0, $v['money'], $v['reward'], $v['reward'], $v['uid'] ]);
                $sql_update4->execute([ $v['uid'], 0, $v['money'], 1 ]);//更新用户绑定后消费数据
                ++$i;
            }
            file_put_contents((date('Y-m-d').'_SubCommission_team.log'),date('Y-m-dHis',time()).'-团队结算：'.json_encode(['order'=>$order,'wallet'=>$wallet]));
            if(!empty($wallet)){
                $walletSql =  $this->multArrayInsert('m3_wallet_operation_log',['uid','reward','status','type','extend','extend_id','add_time','describe'],$wallet);
                $this->pdb->exec($walletSql);
                $sql_update2->execute([ 3, $oid ]);
            }
            $this->pdb->commit();
            return true;
        }catch(\PDOException $e){
            if($this->pdb->inTransaction()) $this->pdb->rollBack();
            file_put_contents((date('Y-m-d').'_SubCommission_team_err.log'),date('Y-m-dHis',time()).'-teamSettlement-团队结算异常：'.json_encode(['order'=>$order,'err'=>$e->getMessage()]));
            return $e->getMessage();
        }catch(\Exception $e){
            if($this->pdb->inTransaction()) $this->pdb->rollBack();
            file_put_contents((date('Y-m-d').'_SubCommission_team_err.log'),date('Y-m-dHis',time()).'-teamSettlement-团队结算异常：'.json_encode(['order'=>$order,'err'=>$e->getMessage()]));
            return $e->getMessage();
        }
    }

    /*
     * 分佣结算
     */
    public function shareSettlement($uid,$order,$mtype){
        $oid = 0;
        try{
            if(empty($uid)) throw new \Exception('没有可分配用户！');
            if(empty($order)||!is_array($order)) throw new \Exception('没有可分配订单！');
            #组装用户信息和钱包信息
            foreach($order as $kk=>$vv){
                $oid = $vv['oid'];
                $sm = $this->pdb->query("Select volume_balance,volume_total,miao,miaos,pre_miao,wait_miao,consume,teams from m3_user_wallet where uid={$vv['uid']} and is_delete=0", \PDO::FETCH_ASSOC);
                $userWallet = $sm->fetch();
                $order[$kk] = array_merge($order[$kk], $userWallet?:[]);
            }
            #按等级进行分佣 同等级按管理津贴算，非同等级按团队佣金算
            $miao = $wallet = [];$i = 0;$time = time();
            $sql_update = $this->pdb->prepare("Update m3_user_wallet set miao=?,miaos=?,wait_miao=? where uid=?");
            $sql_update1 = $this->pdb->prepare("Update m3_miao_log set `status`=? where oid=? and type in ($mtype)");
            $this->pdb->beginTransaction();
            foreach($order as $k=>$v){
                if($v['uid'] == $uid){
                    if($v['reward']>0){
                        $i=$i+1;
                        $wallet[$i] = ['uid'=>$v['uid'],'reward'=>$v['reward'],'status'=>1,'type'=>2,'extend'=>'order','extend_id'=>$oid,'add_time'=>$time,'describe'=>'分享结算(喵呗)&扣除待结算记录'];
                    }
                    $sql_update->execute([ $v['miao']+$v['reward'], $v['miaos']+$v['reward'], ($v['wait_miao']-$v['reward'])>0 ? $v['wait_miao']-$v['reward'] : 0, $v['uid'] ]);
                }else{
                    if($v['reward']>0){
                        $i=$i+1;
                        $wallet[$i] = ['uid'=>$v['uid'],'reward'=>$v['reward'],'status'=>1,'type'=>2,'extend'=>'order','extend_id'=>$oid,'add_time'=>$time,'describe'=>'分享结算(喵呗)&扣除待结算记录'];
                    }
                    $sql_update->execute([ $v['miao']+$v['reward'], $v['miaos']+$v['reward'], ($v['wait_miao']-$v['reward'])>0 ? $v['wait_miao']-$v['reward'] : 0, $v['uid'] ]);
                }
                ++$i;
            }
            file_put_contents((date('Y-m-d').'_SubCommission_share.log'),date('Y-m-dHis',time()).'-分享结算：'.json_encode(['userInvite'=>$order,'order'=>$order,'miao'=>$miao,'wallet'=>$wallet]));
            if(!empty($wallet)){
                $walletSql =  $this->multArrayInsert('m3_wallet_operation_log',['uid','reward','status','type','extend','extend_id','add_time','describe'],$wallet);
                $this->pdb->exec($walletSql);
                $sql_update1->execute([ 3, $oid ]);
            }
            $this->pdb->commit();
            return true;
        }catch(\PDOException $e){
            if($this->pdb->inTransaction()) $this->pdb->rollBack();
            file_put_contents((date('Y-m-d').'_SubCommission_share_err.log'),date('Y-m-dHis',time()).'-shareSettlement-分享结算异常：'.json_encode(['order'=>$order,'err'=>$e->getMessage()]));
            return $e->getMessage();
        }catch(\Exception $e){
            if($this->pdb->inTransaction()) $this->pdb->rollBack();
            file_put_contents((date('Y-m-d').'_SubCommission_share_err.log'),date('Y-m-dHis',time()).'-shareSettlement-分享结算异常：'.json_encode(['order'=>$order,'err'=>$e->getMessage()]));
            return $e->getMessage();
        }
    }

    /**
     * 多条数据同时转化成插入SQL语句
     * @ CreatBy:IT自由职业者
     * @param string $table 表名
     * @$arr_key是表字段名的key：$arr_key=array("field1","field2","field3")
     * @param array $arr是字段值 数组示例 arrat(("a","b","c"), ("bbc","bbb","caaa"),('add',"bppp","cggg"))
     * @return string
     */
    public function multArrayInsert($table,$arr_key, $arr, $split = '`') {

        $arrValues = array();
        if (empty($table) || !is_array($arr_key) || !is_array($arr)) return false;
        $sql = "INSERT INTO %s( %s ) values %s ";
        foreach ($arr as $k => $v) {
            $arrValues[$k] = "'".implode("','",array_values($v))."'";
        }

        $sql = sprintf($sql, $table, "{$split}" . implode("{$split} ,{$split}", $arr_key) . "{$split}", "(" . implode(") , (", array_values($arrValues)) . ")");
        return $sql;
    }

    /*
     * 获取上级级
     */
    public function loopTop($uid){
        try{
            $sm = $this->pdb->query("Select uid,`level` from m3_user_invite WHERE uid={$uid}", \PDO::FETCH_ASSOC);
            $map = $sm->fetch();
            return $map;
        }catch(\PDOException $e){
            return $e->getMessage();
        }catch(\Exception $e){
            return $e->getMessage();
        }
    }

    /*
     * 递归获取下级
     */
    public function loopInvite($uid){
        $sm = $this->pdb->query("Select uid,upid,pid from m3_user_invite WHERE upid={$uid}", \PDO::FETCH_ASSOC);
        $map = $sm->fetchAll();
        if(empty($map)) return [];
        foreach($map as $k => $v)
        {
            $item = $this->loopInvite($v['uid']);
            if($item)
                $map = array_merge($map,$item);
        }
        return $map;
    }

}

//function delValue($arr) {
//    if($arr['allow'] == 1) return true;
//    return false;
//}

//swoole_timer_tick( 30000 , function(){
//    $Gz = new SubCommissionModule();
//    $Gz->autoCalculate(2,1274);
//});


$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
//$redis->auth('zeng123456');
#redis监听key失效事件
$redis->psubscribe(array('__keyevent@9__:expired'), 'keyCallback');
#redis监听回调
function keyCallback($_redis, $pattern, $channel, $message) {
    //echo "Pattern : $pattern\n";
    //echo "Channel : $channel\n";
    echo "Message : $message\n";
    if(!empty($message)){
        $type = explode(':',$message);
        if(empty($type)||empty($type[0])||empty($type[1])||empty($type[2])) return false;
        if($type[0] == 'mmei_miaolog'){
            $Gz = new SubCommissionModule();
            $status = $type[1] == 'sale' ? 1 : 2;
            $res = $Gz->autoCalculate($status,$type[2]);#调用结算方法
            if($res != true){
                #设置不成功则redis重试和重试次数
                if(isset($type[3])){
                    if($type[3] >= 3){
                        echo '超过次数';
                        return false;
                    }
                    $msg = "{$type[0]}:{$type[1]}:{$type[2]}:".($type[3]+1);
                }else $msg = $message.':1';
                #设置重试间隔为5秒
                $redis = new Redis();
                $redis->connect("127.0.0.1", 6379);
//                $redis->auth('zeng123456');
                $redis->select(9);
                $redis->setex($msg, 5, 1);
            }
        }
    }
}

